package nl.sanity.net
{
	import flash.display.Loader;
	import flash.errors.IllegalOperationError;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLRequest;
	import flash.system.ApplicationDomain;
	import flash.system.LoaderContext;
	
	/**
	* 	Load an swf (no AS1/AS2) inside the same ApplicationDomain as the current application.
	* 	This means classes inside the loaded swf can be accessed directly.
	* 	Based on example from Flash Help. 
	* 
	* 	@langversion ActionScript 3
	*
	* 	@author A. Gosman
	* 	@since 	03/21/2009
	* 	@see: http://livedocs.adobe.com/flex/201/html/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Book_Parts&file=18_Client_System_Environment_175_4.html
	* 
	*  Usage:
	* 
	* 	Inside your application create an instance of the ClassLoader and load in an swf:
	* 
	* 			var loader:ClassLoader = new ClassLoader();
    *       	loader.addEventListener( IOErrorEvent.IO_ERROR, loadErrorHandler);
    *        	loader.addEventListener( SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler );
    *        	loader.addEventListener( Event.COMPLETE, classLoadedHandler );
    *        	loader.load("RunTimeClass.swf");
    * 
    * 	In the COMPLETE handler, you can access methods of classes inside the loaded swf:
    * 
    *	 	var RunTimeClassReference:Class	= _loader.getClass( "MyClass" );
    *       var classInstance:Object 		= new RunTimeClassReference();
	*		classInstance.doSomething(); 
	* 
	*/
	public class ClassLoader extends EventDispatcher 
	{
	    protected var _loader				:Loader;
	    protected var _swfLibrary			:String;
	    protected var _request				:URLRequest;
	    protected var _loadedClass			:Class;
	
	    public function ClassLoader() 
	    {
	
	        _loader 					= new Loader();
	        _loader.contentLoaderInfo.addEventListener( Event.COMPLETE,completeHandler );
	        _loader.contentLoaderInfo.addEventListener( IOErrorEvent.IO_ERROR,ioErrorHandler );
	        _loader.contentLoaderInfo.addEventListener( SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler );
	    }
	
	    public function load( url:String ):void 
	    {
	        _swfLibrary 				= url;
	        _request 					= new URLRequest( _swfLibrary );
	        var context:LoaderContext 	= new LoaderContext();
	        context.applicationDomain	= ApplicationDomain.currentDomain;
	        _loader.load( _request, context );
	    }
	
	    public function getClass( className:String ):Class 
	    {
	        try 
	        {
				return _loader.contentLoaderInfo.applicationDomain.getDefinition( className ) as Class;
	        } 
	        catch (e:Error) 
	        {
	            throw new IllegalOperationError( className + " definition not found in " + _swfLibrary );
	        }
	        return null;
	    }
	
	    protected function completeHandler( event:Event ):void 
	    {
	        dispatchEvent( new Event( Event.COMPLETE ) );
	    }
	
	    protected function ioErrorHandler( event:IOErrorEvent ):void 
	    {
	        dispatchEvent( new IOErrorEvent( IOErrorEvent.IO_ERROR ) );
	    }
	
	    protected function securityErrorHandler( event:SecurityErrorEvent ):void 
	    {
	        dispatchEvent( new SecurityErrorEvent( SecurityErrorEvent.SECURITY_ERROR ) );
	    }
	}
}
